﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml.Input;
using Controls = Windows.UI.Xaml.Controls;
using Shapes = Windows.UI.Xaml.Shapes;
using Windows.UI.Xaml.Media;
using Windows.UI;
using Windows.UI.Xaml.Controls;
using BoolanSlide.ElementMenu;
using Windows.UI.Xaml;
using Windows.Foundation;
using BoolanSlide.RedoUndo;
using Windows.UI.Xaml.Media.Imaging;
using Configuration;
using BoolanSlide.Language;

namespace BoolanElement
{
    public class BooLine : BooLineBase, IFocusEllOperation, ILineStyleController
    {
        public Shapes.Line Line;
       // public Controls.Grid FullGrid;
        TranslateTransform topT;
        TranslateTransform bottomT;
        public Shapes.Line FindLine;  
        ControlPanel lineControlPanel;
        BooLineElement lineElement;
        public BooLineElement LineElement
        {
            get
            {
                return lineElement;
            }
        }

        public override BooElement Element
        {
            set { lineElement = (BooLineElement)value; }
            get { return lineElement; }
        }

        LineMenu lineMenu;
        public LineMenu LineMenu
        {
            get { return lineMenu; }
        }

        public override MenuBase UIMenu
        {
            get { return lineMenu; }
        }

        public BooLine(BooLineElement element, SaveForRedoUndo saveForRedoUndo)
            : base(element)
        {
            this.lineElement = element;
            InitOriginal();
            Focus.InitFocusEvent(this);
            InitLineControlPanel();
            base.saveForRedoUndo = saveForRedoUndo;
            topT = new TranslateTransform();
            bottomT = new TranslateTransform();

            Focus.FocusElls.left_top_ell.RenderTransform = topT;
            Focus.FocusElls.right_bottom_ell.RenderTransform = bottomT;
            LostFocus();
            LanguageManager.LanguageChanged += LanguageManager_LanguageChanged;
        }

        void LanguageManager_LanguageChanged(object sender)
        {
            lineControlPanel.ModifyTab(LanguageManager.StyleTabNormal2, LanguageManager.StyleTabDown2, LanguageManager.StyleTabDown2, 0);
        }

        public BooLine(BooLineElement element):base(element)
        {
            this.lineElement = element;
            InitForThumbNails();
        }

        private void InitOriginal()
        {
            CreateShape();
            InitializeActionMap(BooCanvas);
            InitContextMenu();
            Focus.InsertFocusEllipses(BooCanvas);
            Focus.FocusElls.left_top_ell.Margin = new Thickness(this.lineElement.PointX.X - FocusEllipses.FocusTouchAreaLength / 2,
                this.lineElement.PointX.Y-FocusEllipses.FocusTouchAreaLength/2,0,0);
            Focus.FocusElls.right_bottom_ell.Margin = new Thickness(this.lineElement.PointY.X - FocusEllipses.FocusTouchAreaLength / 2,
                this.lineElement.PointY.Y - FocusEllipses.FocusTouchAreaLength / 2, 0, 0);
        }

        private void InitForThumbNails()
        {
            CreateShape();
            ApplyTransform(BooCanvas);
            BooCanvas.ManipulationMode = ManipulationModes.All;
        }

        public void InitContextMenu()
        {
            lineMenu = new LineMenu(this);
        }

        public void CreateShape()
        {
            InitLine();
            InitFindLine();
            InitCanvas();
            BooCanvas.Children.Add(FindLine);
            BooCanvas.Children.Add(Line);      
        }

        public void InitLine()
        {
            Line = new Shapes.Line();
            Line.X1 = lineElement.PointX.X;
            Line.Y1 = lineElement.PointX.Y;
            Line.X2 = lineElement.PointY.X;
            Line.Y2 = lineElement.PointY.Y;
            Line.Stroke = new SolidColorBrush(lineElement.LineColor);
            Line.StrokeThickness = LineElement.BorderWidth;

            Line.PointerPressed += Line_PointerPressed;
            Line.PointerReleased += Line_PointerReleased;
        }

        void Line_PointerReleased(object sender, PointerRoutedEventArgs e)
        {
            if (System.DateTime.Now.Ticks - PressedTicks < GlobalVariable.ShowMenuTime && Manipulationed == false)
            {
                if (this.lineMenu != null)
                    this.LineMenu.ShowMenu();
            }
            Manipulationed = false;
        }

        void Line_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
            PressedTicks = System.DateTime.Now.Ticks;
            Manipulationed = false;
        }

        public void InitFindLine()
        {
            FindLine = new Shapes.Line();
            FindLine.X1 = lineElement.PointX.X;
            FindLine.Y1 = lineElement.PointX.Y;
            FindLine.X2 = lineElement.PointY.X;
            FindLine.Y2 = lineElement.PointY.Y;
            FindLine.Stroke = new SolidColorBrush(Colors.Transparent);
            FindLine.StrokeThickness = 20;
            FindLine.PointerPressed += Line_PointerPressed;
            FindLine.PointerReleased += Line_PointerReleased;
        }

        public void InitCanvas()
        {
            BooCanvas = new Controls.Canvas();
            BooCanvas.Background = new SolidColorBrush(Colors.SkyBlue);
        }

        public void InitLineControlPanel()
        {
            lineControlPanel = new ControlPanel();
            LineStyle lineStyle = new LineStyle();
            lineControlPanel.AddTab(LanguageManager.StyleTabNormal2, LanguageManager.StyleTabDown2, LanguageManager.StyleTabDown2, lineStyle);
        }

        public override void LoadFromElement(BooElement booElement)
        {
            base.LoadFromElement(booElement);
            base.InitializeActionMap(BooCanvas);
            Line.X1 = lineElement.PointX.X;
            Line.Y1 = lineElement.PointX.Y;
            Line.X2 = lineElement.PointY.X;
            Line.Y2 = lineElement.PointY.Y;
            FindLine.X1 = lineElement.PointX.X;
            FindLine.Y1 = lineElement.PointX.Y;
            FindLine.X2 = lineElement.PointY.X;
            FindLine.Y2 = lineElement.PointY.Y;

            Focus.FocusElls.left_top_ell.Margin = new Thickness(-FocusEllipses.FocusTouchAreaLength / 2,-FocusEllipses.FocusTouchAreaLength / 2, 0, 0);
            Focus.FocusElls.right_bottom_ell.Margin = new Thickness(- FocusEllipses.FocusTouchAreaLength / 2,- FocusEllipses.FocusTouchAreaLength / 2, 0, 0);
            if (topT != null && bottomT != null)
            {
                topT.X = lineElement.PointX.X;
                topT.Y = lineElement.PointX.Y;
                bottomT.X = lineElement.PointY.X;
                bottomT.Y = lineElement.PointY.Y;
            }
            ApplyStyleChange();
            BooCanvas.Margin = lineElement.ElementTransform.Margin;
        }

        public override void LostFocus()
        {
            base.LostFocus();
            this.lineMenu.HideMenu();
            HideLineControlPanel();
        }

        public override void GotFocus()
        {
            base.GotFocus();
            Focus.FocusElls.middle_top_ell.Visibility = Visibility.Collapsed;
            Focus.FocusElls.right_top_ell.Visibility = Visibility.Collapsed;
            Focus.FocusElls.right_middle_ell.Visibility = Visibility.Collapsed;
            Focus.FocusElls.middle_bottom_ell.Visibility = Visibility.Collapsed;
            Focus.FocusElls.left_middle_ell.Visibility = Visibility.Collapsed;
            Focus.FocusElls.left_bottom_ell.Visibility = Visibility.Collapsed;
            Focus.FocusElls.ScopeRectangle.Visibility = Visibility.Collapsed;
            Focus.FocusElls.rotate_ell.Visibility = Visibility.Collapsed;

            ShowLineControlPanel(this);
        }

        public void left_top_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            double width = e.Delta.Translation.X;
            double height = e.Delta.Translation.Y;

            this.lineElement.PointX = new Point(Line.X1+width, Line.Y1+height);

            lineElement.PropertyChange("Shape");
            e.Handled = true;
        }

        public void right_bottom_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            double width = e.Delta.Translation.X;
            double height = e.Delta.Translation.Y;

            this.lineElement.PointY = new Point(Line.X2+width, Line.Y2+height);

            lineElement.PropertyChange("Shape");
            e.Handled = true;
        }

        public void right_bottom_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            RedoUndoHelper.SaveStatus(this);
            e.Handled = true;
        }

        public void left_top_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            RedoUndoHelper.SaveStatus(this);
            e.Handled = true;
        }

        public void middle_top_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void right_top_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void right_middle_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void middle_bottom_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void left_bottom_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void left_middle_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void middle_top_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void right_top_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void right_middle_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void middle_bottom_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void left_bottom_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void left_middle_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void ShowLineControlPanel(IStyleController lineController)
        {
            if (lineControlPanel != null)
            {
                lineControlPanel.ShowControlPanel(lineController);
            }
        }

        public void HideLineControlPanel()
        {
            if (lineControlPanel != null)
            {
                lineControlPanel.HideControlPanel();
            }
        }

        public void ChangeBorderColor(Color color)
        {
            lineElement.LineColor = color;
            lineElement.PropertyChange("Style");
            RedoUndoHelper.SaveStatus(this);
        }

        public Color GetBorderColor()
        {
            return ((SolidColorBrush)Line.Stroke).Color;
        }

        public void ChangeBorderWidth(double width, bool isSave = false)
        {
            lineElement.BorderWidth = width;
            lineElement.PropertyChange("Style");
            if(isSave)
                RedoUndoHelper.SaveStatus(this);
        }

        public double GetBorderWidth()
        {
            return Line.StrokeThickness;
        }

        public override BooLineBaseElement BooLineBaseElement
        {
            get { return lineElement; }
        }

        public override Point GetMenuDisplayPosition()
        {
            Point ret = new Point();
            double yLoc = 0;
            if (LineElement.PointX.Y < LineElement.PointY.Y)
            {
                yLoc = lineElement.PointX.Y;
            }
            else
            {
                yLoc = LineElement.PointY.Y;
            }
            yLoc += LineElement.ElementTransform.Translate.Y;

            double xLoc = (LineElement.PointX.X + LineElement.PointY.X) / 2 + LineElement.ElementTransform.Translate.X;
            return new Point(xLoc,yLoc);
        }

        public override void ApplyShapeChange()
        {
            Line.X1 = lineElement.PointX.X;
            Line.Y1 = lineElement.PointX.Y;
            Line.X2 = lineElement.PointY.X;
            Line.Y2 = lineElement.PointY.Y;
            FindLine.X1 = lineElement.PointX.X;
            FindLine.Y1 = lineElement.PointX.Y;
            FindLine.X2 = lineElement.PointY.X;
            FindLine.Y2 = lineElement.PointY.Y;

            Focus.FocusElls.left_top_ell.Margin = new Thickness(-FocusEllipses.FocusTouchAreaLength / 2, -FocusEllipses.FocusTouchAreaLength / 2, 0, 0);
            Focus.FocusElls.right_bottom_ell.Margin = new Thickness(-FocusEllipses.FocusTouchAreaLength / 2, -FocusEllipses.FocusTouchAreaLength / 2, 0, 0);
            if (topT != null)
            {
                topT.X = lineElement.PointX.X;
                topT.Y = lineElement.PointX.Y;
            }
            if (bottomT != null)
            {
                bottomT.X = lineElement.PointY.X;
                bottomT.Y = lineElement.PointY.Y;
            }
            BooCanvas.Margin = lineElement.ElementTransform.Margin;
        }

        public override void ApplyStyleChange()
        {
            Line.Fill = new SolidColorBrush(lineElement.LineColor);
            Line.Stroke = new SolidColorBrush(lineElement.LineColor);
            Line.StrokeThickness = lineElement.BorderWidth;
        }


        public int GetZIndex()
        {
            return this.lineElement.ElementTransform.ZIndex;
        }

        public void ChangeZIndexTo(int index)
        {
            this.lineElement.ElementTransform.ZIndex = index;
        }

        public void rotate_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void rotate_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }


        public void rotate_ell_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }
    }
}
